/** computed枚举成员 和 constant枚举成员

 分成computed和constant两种枚举成员的意义在于
 enums without initializers either need to be first, or have to come after numeric enums initialized with numeric constants or other constant enum members

 看下面例子
*/
enum Char{
  //const 编译阶段就会得到值
  a // 默认值为0
  , b = Char.a // 可以是引用
  , c = 1 + 3 // 可以是表达式
  // ,f //5

  //computed 程序运行时得到结果
  , d = Math.random()
  , e = '123'.length
  // , f // 会报错 这样的情景(在computed枚举成员后面的话)下必须赋值
}

/** 每个枚举成员都带有一个值，它可以是 常量或 计算出来的。 当满足如下条件时，枚举成员被当作是常量： */
//1. 它是枚举的第一个成员且没有初始化器，这种情况下它被赋予值 0：
// E.X is constant:
enum E { X }
//2. 它没有初始化且它之前的枚举成员是一个 数字常量。 这种情况下，当前枚举成员的值为它上一个枚举成员的值加1。

/* 3.枚举成员使用 常量枚举表达式初始化。 常数枚举表达式是TypeScript表达式的子集，它可以在编译阶段求值。 当一个表达式满足下面条件之一时，它就是一个常量枚举表达式：
> The enum member is initialized with a constant enum expression. A constant enum expression is a subset of TypeScript expressions that can be fully evaluated at compile time. An expression is a constant enum expression if it is:

  + 一个枚举表达式字面量（主要是字符串字面量或数字字面量）
  + 一个对之前定义的常量枚举成员的引用（可以是在不同的枚举类型中定义的）
  + 带括号的常量枚举表达式
  + 一元运算符 +, -, ~其中之一应用在了常量枚举表达式
  + 常量枚举表达式做为二元运算符 +, -, *, /, %, <<, >>, >>>, &, |, ^的操作对象。 若常数枚举表达式求值后为 NaN或 Infinity，则会在编译阶段报错。
*/

/** 除了以上三种情况 其余皆为computed enum member*/

enum FileAccess {
  // constant members
  None,
  Read    = 1 << 1,
  Write   = 1 << 2,
  ReadWrite  = Read | Write,
  // computed member
  G = "123".length
}
